﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using VosSoft.ZuneLcd.Api;

namespace VosSoft.ZuneLcd.Color
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainPage : UserControl
    {
        private readonly ControlTemplate stopIcon, playIcon, pauseIcon, fastForwardIcon;

        private readonly BitmapImage muteOnIcon, muteOffIcon;
        private readonly BitmapImage repeatOnIcon, repeatOffIcon;
        private readonly BitmapImage shuffleOnIcon, shuffleOffIcon;
        private readonly BitmapImage ratingInvalidIcon, ratingUnratedIcon, ratingLikeIcon, ratingDontLikeIcon;

        private readonly DrawingImage defaultBackground;

        private readonly Storyboard pageTransitionLeft, pageTransitionRight;
        private readonly Storyboard trackTransitionOut, trackTransitionIn;
        private readonly Storyboard dynamicTransitionOut, dynamicTransitionIn;

        private Track currentTrack;

        private DispatcherTimer dynamicTimer;
        private string dynamicText;
        private byte dynamicCounter = 0;

        private delegate void Action();

        private void Invoke(Action action)
        {
            if (CheckAccess())
                action();
            else
                Dispatcher.BeginInvoke(action, DispatcherPriority.Render);
        }

        internal MainPage()
        {
            InitializeComponent();

            stopIcon = (ControlTemplate)FindResource("StopIcon");
            playIcon = (ControlTemplate)FindResource("PlayIcon");
            pauseIcon = (ControlTemplate)FindResource("PauseIcon");
            fastForwardIcon = (ControlTemplate)FindResource("FastForwardIcon");

            muteOffIcon = (BitmapImage)FindResource("MuteOffIcon");
            muteOnIcon = (BitmapImage)FindResource("MuteOnIcon");

            repeatOffIcon = (BitmapImage)FindResource("RepeatOffIcon");
            repeatOnIcon = (BitmapImage)FindResource("RepeatOnIcon");

            shuffleOffIcon = (BitmapImage)FindResource("ShuffleOffIcon");
            shuffleOnIcon = (BitmapImage)FindResource("ShuffleOnIcon");

            ratingInvalidIcon = (BitmapImage)FindResource("RatingInvalidIcon");
            ratingUnratedIcon = (BitmapImage)FindResource("RatingUnratedIcon");
            ratingLikeIcon = (BitmapImage)FindResource("RatingLikeIcon");
            ratingDontLikeIcon = (BitmapImage)FindResource("RatingDontLikeIcon");

            defaultBackground = (DrawingImage)FindResource("DefaultBackground");

            pageTransitionLeft = (Storyboard)FindResource("PageTransitionLeft");
            pageTransitionRight = (Storyboard)FindResource("PageTransitionRight");

            trackTransitionOut = (Storyboard)FindResource("TrackTransitionOut");
            trackTransitionIn = (Storyboard)FindResource("TrackTransitionIn");

            dynamicTransitionOut = (Storyboard)FindResource("DynamicTransitionOut");
            dynamicTransitionIn = (Storyboard)FindResource("DynamicTransitionIn");

            dynamicTimer = new DispatcherTimer(TimeSpan.FromSeconds(4.0), DispatcherPriority.Input, DynamicTimer_Tick, Dispatcher.CurrentDispatcher);
            dynamicTimer.Stop();
        }

        internal void SetTrackStateIcon(TrackState trackState, bool fastForwarding)
        {
            switch (trackState)
            {
                case TrackState.Playing:
                    ucTrackStateIcon.Template = fastForwarding ? fastForwardIcon : playIcon;
                    dynamicTimer.Start();
                    break;
                case TrackState.Paused:
                    ucTrackStateIcon.Template = pauseIcon;
                    dynamicTimer.Start();
                    break;
                default:
                    ucTrackStateIcon.Template = stopIcon;
                    dynamicTimer.Stop();
                    break;
            }
        }

        internal void SetMute(bool value)
        {
            imgMuteIcon.Source = value ? muteOnIcon : muteOffIcon;
        }

        internal void SetRepeat(bool value)
        {
            imgRepeatIcon.Source = value ? repeatOnIcon : repeatOffIcon;
        }

        internal void SetShuffle(bool value)
        {
            imgShuffleIcon.Source = value ? shuffleOnIcon : shuffleOffIcon;
        }

        internal void SetRating(TrackRating rating)
        {
            switch (rating)
            {
                case TrackRating.Unrated:
                    imgRatingIcon.Source = ratingUnratedIcon;
                    break;
                case TrackRating.Like:
                    imgRatingIcon.Source = ratingLikeIcon;
                    break;
                case TrackRating.DontLike:
                    imgRatingIcon.Source = ratingDontLikeIcon;
                    break;
                default:
                    imgRatingIcon.Source = ratingInvalidIcon;
                    break;
            }
        }

        internal void ChangeTrack(Track track, bool isMainPage)
        {
            currentTrack = track;

            dynamicText = currentTrack.Title;
            dynamicCounter = 0;
            txtDynamic.BeginStoryboard(dynamicTransitionOut, HandoffBehavior.SnapshotAndReplace);

            SetCover(currentTrack.CoverUrl);
            txtDuration.Text = currentTrack.DurationFormat;

            if (isMainPage)
                gridMain.BeginStoryboard(trackTransitionOut, HandoffBehavior.SnapshotAndReplace);
        }

        internal void GoToNextPage(bool goToMainPage, bool left)
        {
            if (goToMainPage)
            {
                if (currentTrack != null)
                    SetTrack();

                gridMain.RenderTransform = new TranslateTransform(left ? 320.0 : -320.0, 0.0);
                gridTracks.RenderTransform = new TranslateTransform(0.0, 0.0);
            }
            else
            {
                gridMain.RenderTransform = new TranslateTransform(0.0, 0.0);
                gridTracks.RenderTransform = new TranslateTransform(left ? 320.0 : -320.0, 0.0);
            }

            Storyboard pageTransition = left ? pageTransitionLeft : pageTransitionRight;
            gridMain.BeginStoryboard(pageTransition, HandoffBehavior.SnapshotAndReplace);
            gridTracks.BeginStoryboard(pageTransition, HandoffBehavior.SnapshotAndReplace);
        }

        internal void ChangeTracks(Track[] tracks, int index)
        {
            lstTracks.Items.Clear();
            for (int i = 0; i < tracks.Length; i++)
            {
                lstTracks.Items.Add(new TrackListBoxItem(tracks[i]));
                if (tracks[i].Index == index)
                    lstTracks.SelectedIndex = i;
            }
        }

        internal void SelectPreviousTrack()
        {
            if (lstTracks.SelectedIndex > 0)
            {
                lstTracks.SelectedIndex--;
                return;
            }

            Track selectedTrack = ((TrackListBoxItem)lstTracks.Items[0]).Track; // select first track
            if (selectedTrack.Index > 0) // there is only a previous tracks if this is not the first one (index 0)
                ZuneLcdApi.Instance.GetTracks(selectedTrack.Index - 1, 1, PreviousTrackReceived);
        }

        private void PreviousTrackReceived(Track[] track)
        {
            if (track.Length != 1)
                return;

            Invoke(new Action(delegate()
            {
                lstTracks.Items.RemoveAt(lstTracks.Items.Count - 1); // remove last track
                lstTracks.Items.Insert(0, new TrackListBoxItem(track[0])); // insert at the front
                lstTracks.SelectedIndex = 0; // select the first track
            }));
        }

        internal void SelectNextTrack()
        {
            if (lstTracks.SelectedIndex < lstTracks.Items.Count - 1)
            {
                lstTracks.SelectedIndex++;
                return;
            }

            Track selectedTrack = ((TrackListBoxItem)lstTracks.Items[lstTracks.Items.Count - 1]).Track; // select last track
            if (selectedTrack.Index < ZuneLcdApi.Instance.TrackCount - 1) // there ist only a next tracks if this is not the last one
                ZuneLcdApi.Instance.GetTracks(selectedTrack.Index + 1, 1, NextTrackReceived);
        }

        private void NextTrackReceived(Track[] track)
        {
            if (track.Length != 1)
                return;

            Invoke(new Action(delegate()
            {
                lstTracks.Items.RemoveAt(0); // remove first track
                lstTracks.SelectedIndex = lstTracks.Items.Add(new TrackListBoxItem(track[0])); // append at the end and selects the last track
            }));
        }

        private void TrackTransitionOut_Completed(object sender, EventArgs e)
        {
            SetTrack();
            gridMain.BeginStoryboard(trackTransitionIn, HandoffBehavior.SnapshotAndReplace);
        }

        private void SetTrack()
        {
            txtArtist.Text = currentTrack.Artist.ToUpper();
            txtAlbum.Text = currentTrack.Album.ToUpper();
            if (currentTrack.ReleaseYear > 0)
                txtAlbum.Text += " (" + currentTrack.ReleaseYear + ")";
            txtTitle.Text = currentTrack.Title;
        }

        private void SetCover(string url)
        {
            if (!string.IsNullOrEmpty(url))
            {
                try
                {
                    Uri coverUri = new Uri(url, UriKind.Absolute);
                    if (System.IO.File.Exists(coverUri.LocalPath))
                    {
                        brdCover.Visibility = Visibility.Visible;
                        imgCover.Source = new BitmapImage(coverUri);

                        return;
                    }
                }
                catch (UriFormatException)
                {
                }
            }

            brdCover.Visibility = Visibility.Collapsed;
            imgCover.Source = defaultBackground;
        }

        private void DynamicTimer_Tick(object sender, EventArgs e)
        {
            string newDynamicText = string.Empty;

            if (dynamicCounter == 0)
                if (!string.IsNullOrEmpty(currentTrack.Artist))
                    newDynamicText = currentTrack.Artist;
                else
                    dynamicCounter++;

            if (dynamicCounter == 1)
                if (!string.IsNullOrEmpty(currentTrack.Album))
                    newDynamicText = currentTrack.Album;
                else
                    dynamicCounter++;

            if (dynamicCounter == 2)
                newDynamicText = currentTrack.Title;

            if (++dynamicCounter > 2)
                dynamicCounter = 0;

            if (newDynamicText != dynamicText)
            {
                dynamicText = newDynamicText;
                txtDynamic.BeginStoryboard(dynamicTransitionOut, HandoffBehavior.SnapshotAndReplace);
            }
        }

        private void DynamicTransitionOut_Completed(object sender, EventArgs e)
        {
            txtDynamic.Text = dynamicText;
            txtDynamic.BeginStoryboard(dynamicTransitionIn, HandoffBehavior.SnapshotAndReplace);
        }
    }
}
